package com.yc.http;

import com.google.gson.Gson;

import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * /docs/index.html?a=1&b=2    地址参数
 */

// 请求对象
public class HttpServletRequest {

    String method;
    String requestURI;
    String protocol;
    Map<String,String> headerMap = new HashMap<>();
    Map<String, List<String>> parameterMap = new HashMap<>();

    public HttpServletRequest(Socket socket) throws IOException {
        System.out.println("解析请求开始...");
        InputStream in = socket.getInputStream();
        byte[] bytes = new byte[9096];
        int count = in.read(bytes);
        String head = new String(bytes,0,count);

        System.out.println(head);
        String[] lines = head.split("\r\n");
        String body = "";
        boolean parseBody = false;
        for (int i = 0; i < lines.length; i++) {
            if(i==0){
                // 头行
                String[] items = lines[i].split(" ");
                method = items[0];
                requestURI = items[1];
                protocol = items[2];
            } else if (parseBody){
                body += lines[i] + "\r\n";
            } else if( lines[i].isEmpty()){
                // 空行 头与体的分割行
                // 遇到空行, 后的 body 单独解析
//                if(lines.length - 1 > i){
//                    // 提取 body 内容
//                    body = lines[lines.length - 1];
//                }
//                break;
                parseBody = true;
            } else {
                // 头域参数
                String[] items = lines[i].split(": ");
                headerMap.put(items[0], items[1]);
            }
        }

        // 解析地址参数
        parseParameter();

        if(body.isEmpty() == false) {
            // 判断 content-type 的值
            if(headerMap.get("Content-Type").startsWith("application/x-www-form-urlencoded")){
                // 解析 body 内部的参数
                System.out.println("body = " + body);
                parseParameterString(body);
            } else if(headerMap.get("Content-Type").startsWith("application/json")){
                Gson gson = new Gson();
                Map json = gson.fromJson(body, Map.class);
                System.out.println("json = " + json);
                System.out.println("json.getClass() = " + json.getClass());
            } else if(headerMap.get("Content-Type").startsWith("multipart/form-data")){
                // 文件上传请求
                String contentType = headerMap.get("Content-Type");
                String boundary = contentType.replaceAll(".+boundary=-{4}(.+)","$1");
                //System.out.println("body = " + body);
                //System.out.println("boundary = " + boundary);
                String[] items = body.split("-{6}"+boundary);
                for (int i = 1; i < items.length - 1; i++) {
                    // System.out.println("items[i] = " + items[i]);
                    parseFormDataItem(items[i]);
                }
            }
        }

        System.out.println("parameterMap = " + parameterMap);

        System.out.println("解析请求结束...");
    }

    public void parseFormDataItem(String item) throws IOException {
        String[] lines = item.split("\r\n");
        if(lines[1].contains("filename=")){
            // 文件块
            // TODO 使用配置文件保存该路径
            String uplaodPath = "D:/dev/yc138/0628/";
            String filename = lines[1].replaceAll(".+filename=\"(.+)\"","$1");
            String filepath = uplaodPath + filename;

            if(lines[2].endsWith("application/octet-stream")){
                try(FileWriter fw = new FileWriter(filepath)){
                    for (int i = 4; i < lines.length; i++) {
                        if(i>4){
                            fw.write("\r\n");
                        }
                        fw.write(lines[i]);
                    }
                }
            } else {
                // TODO 请自行完善 非文本文件的 存储
            }
        } else {
            // 参数块
            String name = lines[1].replaceAll(".+name=\"(.+)\"","$1");
            String value = "";
            for (int i = 3; i < lines.length; i++) {
                if(i>3){
                    value+="\r\n";
                }
                value += lines[i];
            }
            List<String> list = parameterMap.get(name);
            if(list == null){
                list = new ArrayList<>();
                parameterMap.put(name,list);
            }
            list.add(value);
        }

    }

    public void parseParameter(){
        // a=1  or a= 空字符串  or a 空字符串
        // a=1&b=2&a=3
        // ?user=zs&pwd=123&like=和平&like=踢球
        int index = requestURI.indexOf("?");
        String parameterString;
        // 截取参数字符串
        if (index == -1) {
            return;
        } else {
            parameterString = requestURI.substring(index+1);
            requestURI = requestURI.substring(0, index);
        }
        parseParameterString(parameterString);
    }

    public void parseParameterString(String parameterString){
        //        URLEncoder 用于编码
        // 参数解码
        try {
            parameterString = URLDecoder.decode(parameterString, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        // 拆分参数
        String[] nameValues = parameterString.split("&");
        for (String string : nameValues) {
            String[] nameValue = string.split("=");
            String value="";
            if(nameValue.length == 2){
                // a=1
                value = nameValue[1];
                // a
            } else if(nameValue.length == 1){
                value = "";
            }
            List<String> valueList = parameterMap.get(nameValue[0]);
            //  第一次添加参数时, valueList 为空, 需要创建集合
            if(valueList == null){
                valueList = new ArrayList<>();
            }
            valueList.add(value);
            parameterMap.put(nameValue[0], valueList);
        }
    }






















    public String getRequestURI() {
        return requestURI;
    }

    public void setRequestURI(String requestURI) {
        this.requestURI = requestURI;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public String getProtocol() {
        return protocol;
    }

    public void setProtocol(String protocol) {
        this.protocol = protocol;
    }

    public Map<String, String> getHeaderMap() {
        return headerMap;
    }

    public void setHeaderMap(Map<String, String> headerMap) {
        this.headerMap = headerMap;
    }

    @Override
    public String toString() {
        return "HttpServletRequest{" +
                "method='" + method + '\'' +
                ", requestURI='" + requestURI + '\'' +
                ", protocol='" + protocol + '\'' +
                ", headerMap=" + headerMap +
                '}';
    }
}
